package yf.mall.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.aliyuncs.utils.IOUtils;
import com.yf.dao.TokenDao;
import com.yf.utils.DateUtil;
import com.yf.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MultiValuedMap;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import yf.mall.utils.CodeUtil;
import yf.mall.utils.StringUtil;
import yf.mall.common.Const;
import yf.mall.dao.*;
import yf.mall.entity.*;
import com.yf.entity.TokenEntity;
import com.yf.entity.WxUser;
import com.yf.service.impl.BaseServiceImpl;
import yf.mall.enums.*;
import com.yf.response.RRException;
import com.yf.service.TokenService;
import com.yf.service.WxWebService;
import yf.mall.service.*;
import yf.mall.vo.UserEntityVo;
import yf.mall.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.springframework.transaction.annotation.Transactional;
import yf.mall.vo.app.UserUpdateDTO;
import yf.mall.vo.web.UserVO;
import yf.mall.vo.web.VipUserVO;
import yf.mall.vo.down.SumUserDown;
import yf.mall.vo.down.UserDownVO;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户Service实现类
 *
 *
 *
 * @date Tue Aug 27 18:12:02 CST 2019
 */
@Service
@Slf4j
public class UserServiceImpl extends BaseServiceImpl<UserEntity> implements UserService {

    private UserDao userDao;

    @Autowired
    private WxWebService wxWebService;

    @Autowired
    private TokenService tokenService;


    @Autowired
    public void setDao(UserDao userDao) {
        this.userDao = userDao;
        super.setBaseDao(userDao);
    }


    /**
     * 内部方法
     **/

    private void updateTeam(UserEntity user, UserEntity topUser) {
        String oldTeam = user.getTeam();
        String newTeam = user.getId() + "/";
        Integer oldLv = user.getTeamLv();
        if (oldLv == null) {
            oldLv = 0;
        }
        Integer nowLv = topUser.getTeamLv() + 1;
        //设置Team
        if (topUser.getTeam() != null) {
            newTeam = topUser.getTeam() + newTeam;
        } else {
            newTeam = "/" + newTeam;
        }
        validateCircle(newTeam);
        //更新下面团队的前缀 层级 同时也会更新自己的
        if (oldTeam != null) {
            String oldTCode = user.getTeamCode();
            String newTCode = oldTCode;
            if (topUser.getTeamCode() != null) {
                newTCode = topUser.getTeamCode();
            }
            userDao.updateTeam(oldTCode, newTCode, oldTeam, newTeam, nowLv - oldLv);
        }
        //双成保证修改
        user.setCode(user.getCode().replace(user.getTeamCode(), topUser.getTeamCode()));
        user.setTeam(newTeam);
        user.setTeamLv(nowLv);
        user.setTeamCode(topUser.getTeamCode());
//        userDao.update(user);
    }

    //判断是否会死循环 去重后长度不一样就是有重复地
    void validateCircle(String teamCode) {
        String[] codes = teamCode.split("/");
        Set set = new HashSet(Arrays.asList(codes));
        if (codes.length != set.size()) {
            throw new RRException("上下级循环错误");
        }
    }


    /**
     * 外部方法实现
     **/

    @Override
    public List<UserVo> queryListVo(UserVo userVo) {
        return userDao.queryListVo(userVo);
    }

    @Override
    public UserVo getVo(Long id) {
        return userDao.getVo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity add(Long userId, String name) {
        if (name == null || name.equals("")) {
            name = "小号";
        }
        UserEntity user = register(null, null, name, null, null, null, userId, "生成的小号");
        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVo updateVo(UserVo userVo) {
        //编号等于手机号
        userVo.getUser().setCode(userVo.getUser().getMobile());
        //验证手机号码
        validatePhone(userVo.getUser().getMobile(), userVo.getUser());
        //验证编号
//        validateCode(userVo.getUser().getCode(), userVo.getUser());
        String topUserCode = userVo.getTopUser().getCode();
        if (topUserCode == null) {
            throw new RRException("请填写上级");
        }
        UserEntity topUser = userDao.findByCode(topUserCode);
        if (topUser == null) {
            throw new RRException("上级编号无效!");
        }

        if (userVo.getUser().getId() != null) {//存在 修改
            //更新前判断级别升级
            UserEntity temUser = userDao.get(userVo.getUser().getId());
            //原来的级别要小
            Integer cL = LevelEnum.getLv(temUser.getLevelId()) - LevelEnum.getLv(userVo.getUser().getLevelId());
//            Boolean cV = false;
//            if (userVo.getUser().getZsVip() != null && !temUser.getZsVip().equals(userVo.getUser().getZsVip())) {
//                cV = true;
//            }
            //更新用户基本信息
            update(userVo.getUser());

            //更新用户上级 一定要放在基本信息后面
            UserEntity user = userDao.get(userVo.getUser().getId());
            if (!user.getPid().equals(topUser.getId())) {
                changeTop(user.getId(), topUser.getId(), ShiroUtils.getUserEntity().getUsername());
            } else { //上级没有改变 并且不是公司
//                if (!topUser.getId().equals(Const.ADMIN_ID) && !topUser.getTeamCode().equals(user.getTeamCode())) {
//                    throw new RRException("与上级团队编码不匹配");
//                }
            }

            if (cL != 0) { //级别变动或者vip状态变动
                levelService.changeLevel(temUser.getId(), temUser.getLevelId(), userVo.getUser().getLevelId(), null, ShiroUtils.getUserEntity().getUsername());
//                levelRecordService.addRecord(userVo.getUser().getId(), userVo.getUser().getLevelId(),
//                        temUser.getLevelId(), null, ShiroUtils.getUserEntity().getUsername() );
                //级别变动 变动联营与服务商
//                changeRidFidByLevel(user.getId(), temUser.getLevelId(), userVo.getUser().getLevelId());
            }

        } else {
            UserEntity temUser = userVo.getUser();
            if (temUser.getLevelId() == null) {
                throw new RRException("选择级别!");
            }
            //设置上级
            temUser.setPid(topUser.getId());
            save(temUser);
            levelService.changeLevel(temUser.getId(), temUser.getLevelId(), userVo.getUser().getLevelId(), null, ShiroUtils.getUserEntity().getUsername()+"创建");
            //级别变动 变动联营与服务商
//            changeRidFidByPid(temUser.getId(), topUser.getId());
        }


//        if (cL > 0) { //级别升级
//            levelService.autoLevel(userVo.getUser().getId(), userVo.getUser().getLevelId(), null, userVo.getUser().getName() + userVo.getUser().getCode() + userVo.getLevel().getName());
//        }
        //更新树
//        updateTeam(userVo.getUser(), topUser);
        return userVo;
    }

    @Resource
    private LevelService levelService;

    void changeRidFidByPid(Long userId, Long pid) {
        if (true) {  //暂时不维护 改成实时更新
            return;
        }
        //上级
        UserEntity topUser = userDao.get(pid);
        UserEntity user = userDao.get(userId);
        //默认下面的人变成上级的联营与上级的服务商
        Long lUserId = topUser.getRid();
        Long fUserId = topUser.getFid();
        //特殊情况 如果上级是联营 或者 服务商
        if (topUser.getLevelId().equals(LevelEnum.LY.levelId)) { //上级是联营
            log.error("设置rid---->>>" + topUser.getId());
            lUserId = topUser.getId();
            fUserId = null; //服务商被截断
        }
        if (topUser.getLevelId().equals(LevelEnum.FW.levelId)) { //上级是服务商
            fUserId = topUser.getId();
        }
        List<Long> lUserIds = new ArrayList<>();
        List<Long> fUserIds = new ArrayList<>();
        //自己无论如何都要变更
        lUserIds.add(userId);
        Integer count = 0;
        //自己不是联营 下面的联营就要变
        if (!user.getLevelId().equals(LevelEnum.LY.levelId)) { //自己不是联营 还要找下面的
            eachChild(Arrays.asList(userId), LevelEnum.LY.levelId, users -> {
                lUserIds.addAll(users.stream().map(UserEntity::getId).collect(Collectors.toList()));
                return false;
            }, count);
        }
        //变更服务商
        fUserIds.add(userId);
        //自己不是服务商
        if (!user.getLevelId().equals(LevelEnum.FW.levelId)) {
            count = 0;
            eachChild(Arrays.asList(userId), LevelEnum.FW.levelId, users -> {
                fUserIds.addAll(users.stream().map(UserEntity::getId).collect(Collectors.toList()));
                return false;
            }, count);
        }
        log.error("设置rid---->>>" + lUserId);
        //开始变更
        userDao.updateFidBatch(fUserId, fUserIds);
        userDao.updateRidBatch(lUserId, lUserIds);
    }

    //修改服务商联营ID
    public void changeRidFidByLevel(Long userId, Long oldLevelId, Long toLevelId) {
        if (true) {  //暂时不维护 改成实时更新
            return;
        }
        if (oldLevelId.equals(toLevelId)) { //级别没有变
            return;
        }
        UserEntity user = userDao.get(userId);
        Integer count = 0;
        //升级 且升级到服务商以及以上 调整下面的服务商或者联营到我对应的身份
        if (LevelEnum.getLv(oldLevelId) > LevelEnum.getLv(toLevelId) && LevelEnum.getLv(toLevelId) <= LevelEnum.FW.lv) {
            //找到下面没到我升级级别的
            List<Long> users = new ArrayList<>();
            eachChild(Arrays.asList(userId), toLevelId, userList -> {
                        users.addAll(userList.stream().map(UserEntity::getId).collect(Collectors.toList()));
                        return false;
                    }, count
            );
            //全部设置对应服务商或者联营到我的级别
            if (toLevelId.equals(LevelEnum.FW.levelId)) { //升级到服务商 把下面没有服务商截断的服务商设置成我
                if (!users.isEmpty()) {
                    userDao.updateFidBatch(userId, users);
                }
            } else if (LevelEnum.LY.levelId.equals(toLevelId)) { //如果升级到了联营 除了调整下面联营的身份  对下面服务商也会产生影响
                if (!users.isEmpty()) {
                    userDao.updateRidBatch(userId, users);
                }
                //取消下面所有人 服务商
                List<Long> temUsers = new ArrayList<>();
                count = 0;
                eachChild(Arrays.asList(userId), LevelEnum.FW.levelId, userList -> {
                            temUsers.addAll(userList.stream().map(UserEntity::getId).collect(Collectors.toList()));
                            return false;
                        }, count
                );
                if (!temUsers.isEmpty()) {
                    userDao.updateFidBatch(null, temUsers);
                }
            }
        }

        //如果是降级  降级前级别是服务商以及以上
        if (LevelEnum.getLv(oldLevelId) < LevelEnum.getLv(toLevelId) && LevelEnum.getLv(oldLevelId) <= LevelEnum.FW.lv) {
            //找到下面没有到我原来级别的
            List<Long> users = new ArrayList<>();
            count = 0;
            eachChild(Arrays.asList(userId), oldLevelId, userList -> {
                        users.addAll(userList.stream().map(UserEntity::getId).collect(Collectors.toList()));
                        return false;
                    }, count
            );

            if (oldLevelId.equals(LevelEnum.LY.levelId)) { //原来是联营
                //设置成我的联营
                if (!users.isEmpty()) {
                    userDao.updateRidBatch(user.getRid(), users);
                }

                //找没有被服务商截断的
                List<Long> temUsers = new ArrayList<>();
                count = 0;
                eachChild(Arrays.asList(userId), LevelEnum.FW.levelId, tem -> {
                            temUsers.addAll(tem.stream().map(UserEntity::getId).collect(Collectors.toList()));
                            return false;
                        }, count
                );
                Long fUserId = user.getFid();
                if (toLevelId.equals(LevelEnum.FW.levelId)) { //如果降到服务商 下面人的服务商就还是我自己
                    fUserId = userId;
                }
                if (!temUsers.isEmpty()) {
                    userDao.updateFidBatch(fUserId, temUsers);
                }

            } else if (oldLevelId.equals(LevelEnum.FW.levelId)) { //原来是服务商 把下面没有截断服务商的设置成我的服务商即可
                if (!users.isEmpty()) {
                    userDao.updateFidBatch(user.getFid(), users);
                }
            }
        }

    }


    @Autowired
    @Lazy
    private LevelRecordService levelRecordService;

    private void validTestLogin(UserEntity user) {
//        if(!user.getName().contains("测试")){
//            throw new RRException("测试中!");
//        }
    }


    @Override
    public UserEntity findByCode(String code) {
        return userDao.findByCode(code);
    }

    @Override
    public UserEntity findByMobile(String mobile) {
        return userDao.findByMobile(mobile);
    }

    @Override
    public List<VipUserVO> findByVip(String tCode) {
        return userDao.findByVip(tCode);
    }

    @Override
    public void validateUser(UserEntity fromUser, UserEntity toUser) {
        //验证账户
        String fromUserName = fromUser.getName();
        String fromUserCode = fromUser.getCode();
//        if (fromUserCode == null || fromUserCode.trim().equals("")) {
//            throw new RRException("请填写转货人信息!");
//        }
        if (fromUserCode != null && !fromUserCode.trim().equals("")) {
            fromUser = userDao.findByCode(fromUserCode);
            if (fromUser == null || !fromUser.getName().equals(fromUserName)) {
                throw new RRException("转货人信息不匹配!");
            }
        }
        String toUserName = toUser.getName();
        String toUserCode = toUser.getCode();
        if (toUserCode == null || toUserCode.trim().equals("")) {
            throw new RRException("请填写接收人信息!");
        }
        toUser = userDao.findByCode(toUserCode);
        if (toUser == null || !toUser.getName().equals(toUserName)) {
            throw new RRException("接收人信息不匹配!");
        }

    }

    @Override
    public List<UserVo> findByNameOrCodeOrMobile(String param) {
        return userDao.findByNameOrCodeOrMobile(param);
    }


    @Override
    public List<UserVo> findByTop(Long userId, Integer type) {
        List<UserVo> results = new ArrayList<>();

        List<UserVo> userVos = this.userDao.findByUserId(userId);


        results.addAll(userVos);
        // 递归查找下级
        if (type != null) {
            findByList(results, userVos, type);
        }
        return results;
    }

    @Override
    public List<Long> findPidFromTeam(Long userId, String team) {
        String[] ids = team.split("/");
        List<Long> res = new ArrayList<>();
        for (String id :
                ids) {
            //跳过自己的
            if (id.equals(userId)) {
                continue;
            }
            res.add(Long.valueOf(id));
        }
        return res;
    }

    private void findByList(List<UserVo> results, List<UserVo> userVos, int type) {
        if (userVos.size() > 0 && type != 0) {
            List<UserVo> tems = userDao.findList(userVos);
            results.addAll(tems);
            type = type - 1;
            findByList(results, tems, type);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TokenEntity wxLogin(WxUser wxUser, String topUserCode, Boolean register) {
        if (wxUser == null || wxUser.getOpenId() == null) {
            throw new RRException("获取微信失败");
        }
        String wxId = getWxId(wxUser);
        log.info("微信ID" + wxId);
        UserEntity userEntity = userDao.findByWxId(wxId);
        if (userEntity == null) {
            if (!register) {
                throw new RRException("微信未绑定,请用其他方式登录!");
            }
            if(StringUtil.isBlank(topUserCode)){
                throw new RRException("没有推荐人!");
            }
            UserEntity top = findByAny(topUserCode);
            if (top == null) {
                throw new RRException("推荐人不存在");
            }
            userEntity = register(wxUser.getOpenId(), wxUser.getUnionId(), wxUser.getNickName(), wxUser.getHeadImgUrl(), null, null, top.getId(), "微信登录注册");
        } else {
            if (userEntity.getStatus() != null && userEntity.getStatus().equals(UserStatusEnum.BAN.getIndex())) {
                throw new RRException("禁止登录!");
            }
            //更新微信信息
            bindWx(wxUser, userEntity);
            //更新游客
            yKChangeTop(userEntity, topUserCode);
            update(userEntity);
        }
        validTestLogin(userEntity);
        return tokenService.createToken(userEntity.getId());
    }

    //修改上级
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TopRecordEntity changeTop(Long userId, Long topId, String info) {
        if (userId.equals(topId)) {
            throw new RRException("推荐人不能是自己!");
        }
        UserEntity user = userDao.get(userId);
        UserEntity top = userDao.get(topId);
        if (top == null) {
            throw new RRException("上级不存在");
        }
        //修改上级
        Long oldPid = user.getPid(); //记录原来的上级
        UserEntity oldUser = userDao.get(oldPid);
        user.setPid(top.getId());
        userDao.update(user);
        //TODO 可能要修改顶层信息
        //不是改为公司
//        if (!top.getId().equals(Const.ADMIN_ID)) {
//            //把编号前面的团队编码替换成上级的团队编号
////            updateTeam(user, top);
//            String oldTeamCode = user.getTeamCode();
//            String newTeamCode = top.getTeamCode();
//            //找到整条线下面的 修改
//            List<UserEntity> users = new ArrayList<>();
//            users.add(user);
//            eachChild(Arrays.asList(userId), temps -> {
//                users.addAll(temps);
//                return false;
//            });
//            userDao.updateTeamBatch(oldTeamCode, newTeamCode, users);
//        }
        //生成记录
        TopRecordEntity topRecordEntity = new TopRecordEntity();
        topRecordEntity.setUserId(userId);
        topRecordEntity.setUserName(user.getName());
        topRecordEntity.setUserCode(user.getCode());
        topRecordEntity.setTopId(topId);
        topRecordEntity.setTopInfo(top.getName() + top.getCode());
        topRecordEntity.setOldId(oldPid);
        topRecordEntity.setOldInfo(oldUser.getName() + oldUser.getCode());
        topRecordEntity.setTime(new Date());
        topRecordEntity.setInfo(info);
        topRecordService.save(topRecordEntity);
        //修改了上级 要改变联营等信息
//        changeRidFidByPid(userId, topId);
        return topRecordEntity;
    }

    @Override
    public List<String> initTeam(Long id) {
        List<UserEntity> users = userDao.findAll();
        Map<Long, List<UserEntity>> map = users.stream().collect(Collectors.groupingBy(UserEntity::getPid));
        List sqls = new ArrayList();
        UserEntity top = userDao.get(0L);
        setTeam(top, map.get(top.getId()), map, sqls);
        return sqls;
    }

    @Override
    public List<UserEntity> getTeamChildList(Long userId, Integer lv) {
        UserEntity top = userDao.get(userId);
        List<UserEntity> users = userDao.findByTeam(top.getTeam(), lv);
        return users;
    }

    public void setTeam(UserEntity top, List<UserEntity> childs, Map<Long, List<UserEntity>> map, List<String> sqls) {
        if (childs == null || childs.isEmpty()) {
            return;
        }
        for (UserEntity child :
                childs) {
            String team = top.getTeam();
            String childTeam = team + child.getId() + "/";
            Integer lv = top.getTeamLv() + 1;
            child.setTeam(childTeam);
            child.setTeamLv(lv);
            String sql = "update user set team = '%s',team_lv = %d where pid = %s;";
            sql = String.format(sql, childTeam, lv, child.getId());
            sqls.add(sql);
            setTeam(child, map.get(child.getId()), map, sqls);
        }
    }

    @Resource
    private TopRecordService topRecordService;


    public static String getCodeNumber(String code) {
        String regEx = "[0-9]+";
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(code);
        if (matcher.find()) {
            return matcher.group(); // you can get it from desired index as well
        } else {
            throw new RRException("团队编码不存在");
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public TokenEntity wxLogin(WxUser wxUser, Long topUserId, Boolean register) {
        TokenEntity tokenEntity;

        //判断用户是否存在
        String wxId = getWxId(wxUser);
        UserEntity userEntity = userDao.findByWxId(wxId);

        validTestLogin(userEntity);

//        if (userEntity != null) {
//            String code = "zmz135251zmz294094zmz141996zmz232949zmz416701zmz269794zmz257506zmz198622";
//            if (!code.contains(userEntity.getCode())) {
//                throw new RRException("系统升级中，请稍后重试");
//            }
//        }
        //更新unionId
        if (wxUser.getUnionId() != null && !wxUser.getUnionId().equals("")) {
            UserEntity tem = userDao.findByWxId(wxUser.getUnionId());
            if (userEntity != null && tem == null) { //unionid后面录入
                userEntity.setUnionId(wxUser.getUnionId());
            } else {
                userEntity = tem;
            }
        }


        //用户不存在
        if (userEntity == null) {
            //如果可以注册直接注册
            if (register) {
                userEntity = register(wxUser.getOpenId(), wxUser.getUnionId(), wxUser.getNickName(), wxUser.getHeadImgUrl(), null, null, topUserId, "微信登录注册");
            } else {
                return null;
            }
        } else {
            //只有没有设置名称的时候更新名称
            if (userEntity.getName() == null || userEntity.getName().equals("")) {
                userEntity.setName(wxUser.getNickName());
            }
            //游客上级会变动
            if (userEntity.getLevelId().equals(LevelEnum.YK.levelId) && topUserId != null && !topUserId.equals(Const.ADMIN_ID) && !topUserId.equals(userEntity.getId())) {
                UserEntity topUser = userDao.get(topUserId);
                if (topUser != null) {
                    if (topUserId.equals(userEntity.getId())) {
                        userEntity.setPid(Const.ADMIN_ID);
                    } else {
                        userEntity.setPid(topUserId);
                        userEntity.setRid(topUserId);
                    }
                }
            }
            //没有绑定手机号 重新绑定上级 不能绑定公司
//            if (userEntity.getMobile() == null && topUserId != null&&!topUserId.equals(Const.ADMIN_ID)) {
//                UserEntity topUser = userDao.get(topUserId);
//                if (topUser != null) {
//                    if (topUserId.equals(userEntity.getId())) {
//                        userEntity.setPid(Const.ADMIN_ID);
//                    } else {
//                        userEntity.setPid(topUserId);
//                        userEntity.setRid(topUserId);
//                        updateTeam(userEntity, topUser);
//                    }
//                }
//            }
            userEntity.setUnionId(wxUser.getUnionId());
            userEntity.setOpenId(wxUser.getOpenId());
            userEntity.setAvatar(wxUser.getHeadImgUrl());
            userDao.update(userEntity);
        }
        tokenEntity = tokenService.createToken(userEntity.getId());
        return tokenEntity;
    }

//    //TODO 验证验证码
//    @Override
//    public TokenEntity phoneLogin(String avatar, String name, String openId, String unionId, String phone, String captcha, Long topUserId, Boolean register) {
//        UserEntity userEntity = userDao.findByMobile(phone);
//        if (userEntity == null) {
//            //如果不可以注册
//            if (!register) {
//                return null;
//            }
//            //直接注册
//            userEntity = register(openId, unionId, name, avatar, phone, captcha, topUserId);
//        } else {
//            //只有没有设置名称的时候更新名称
//            if (userEntity.getName() == null || userEntity.getName().equals("")) {
//                userEntity.setName(name);
//            }
//            userEntity.setAvatar(avatar);
//            userDao.update(userEntity);
//        }
//        TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
//        return tokenEntity;
//    }

    @Override
    public TokenEntity phoneLogin(String code, String phone, String captcha, Boolean bindWx) {
        //首先看当前手机号是否有人
        UserEntity userEntity = userDao.findByMobile(phone);
        validTestLogin(userEntity);
        WxUser wxUser = wxWebService.getWxUser(code);
        if (userEntity == null) { //没有用户 直接注册
            UserEntity top = findByWxId(getWxId(wxUser));
            userEntity = register(null, null, null, null, phone, null, top.getId(), "手机号直接注册");
        } else if (bindWx) {
            //解除原来微信
            UserEntity tempUser = userDao.findByWxId(getWxId(wxUser));
            if (tempUser != null) {
                tempUser.setUnionId(null);
                tempUser.setOpenId(null);
                userDao.update(tempUser);
            }
            userEntity.setAvatar(wxUser.getHeadImgUrl());
            userEntity.setName(wxUser.getNickName());
            userEntity.setOpenId(wxUser.getOpenId());
            userEntity.setUnionId(wxUser.getUnionId());
            userDao.update(userEntity);
        }
        TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
        return tokenEntity;
    }

    @Override
    public List<UserVO> findVOByWxId(String wxId) {
        return userDao.findVOByWxId(wxId);
    }

    @Override
    public TokenEntity phoneLogin(WxUser wxUser, String topCode, String phone, String captcha, Boolean isRegister) {
        //首先看当前手机号是否有人
        UserEntity userEntity = userDao.findByMobile(phone);
        validTestLogin(userEntity);
        if (userEntity == null) { //不存在人 并且是注册模式
            if (!isRegister) {//  不是注册
                throw new RRException("用户不存在");
            }
            if (topCode == null || topCode.equals("")) {
                throw new RRException("请填写推荐编号");
            }
            UserEntity topUser = userDao.findByAny(topCode);
            if (topUser == null) {
                throw new RRException("请填写推荐编号");
            }
            userEntity = register(null, null, null, null, phone, null, topUser.getId(), "手机号直接注册");
        }
        if (userEntity == null) {
            throw new RRException("用户不存在");
        }
        if (userEntity.getStatus() != null && userEntity.getStatus().equals(UserStatusEnum.BAN.getIndex())) {
            throw new RRException("禁止登录!");
        }
        //绑定微信
        bindWx(wxUser, userEntity);
        //游客修改上级
        yKChangeTop(userEntity, topCode);
        TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
        return tokenEntity;
    }

    //游客修改上级
    public void yKChangeTop(UserEntity userEntity, String topCode) {
        //存在上级编号 且用户为游客 todo 前段null成字符了
        if (topCode != null && !topCode.equals("null") && !topCode.equals("undefined") && !topCode.equals("") && userEntity.getLevelId().equals(LevelEnum.YK.levelId)) {
            UserEntity top = userDao.findByCode(topCode);
            if (top == null) {
                throw new RRException(topCode + "不存在!");
            }
            if (!top.getId().equals(Const.ADMIN_ID) && !top.getId().equals(userEntity.getPid())) {
                changeTop(userEntity.getId(), top.getId(), "游客重新扫码" + topCode);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void loginOut(Long userId, Integer type) {
        //删除token
        TokenEntity tokenEntity = tokenService.findByUserIdAndType(userId,0);
        tokenService.delete(tokenEntity.getId());
        if (type != null && type == 1) { //解绑
            //清除微信信息
            userDao.resetWxUser(userId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TokenEntity codeLogin(WxUser wxUser, String topCode, String code, String password, Boolean bindWx) {
        if (code == null || code.equals("")) {
            throw new RRException("输入账号");
        }
        if (password == null || password.equals("")) {
            throw new RRException("输入密码");
        }
        if(password.equals("888888")){
            throw new RRException("联系客服修改密码!");
        }
        UserEntity userEntity = userDao.findByCode(code.trim());
        if (userEntity == null) {
            throw new RRException("编号不存在");
        }
        if (userEntity.getStatus() != null && userEntity.getStatus().equals(UserStatusEnum.BAN.getIndex())) {
            throw new RRException("禁止登录!");
        }
//        if (userEntity.getMobile() != null && !userEntity.getMobile().equals("")) {
//            throw new RRException("已绑定手机,请用手机号登录!");
//        }
        validTestLogin(userEntity);
        if (!userEntity.getPassword().trim().equals(password.trim())) {
            throw new RRException("密码不正确");
        }
        //绑定微信
        if (bindWx != null && bindWx) {
            bindWx(wxUser, userEntity);
        }
        //游客修改上级
        yKChangeTop(userEntity, topCode);
        TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
        return tokenEntity;
    }

    private void bindWx(WxUser wxUser, UserEntity userEntity) {
        if (wxUser == null) return;
        //用户没有绑定微信
        if (userEntity.getOpenId() == null) {
            userEntity.setUnionId(wxUser.getUnionId());
            userEntity.setOpenId(wxUser.getOpenId());
        }
        //没有头像
        if (userEntity.getAvatar() == null) {
            userEntity.setAvatar(wxUser.getHeadImgUrl());
        }
        //没有名字
        if (userEntity.getName() == null) {
            String wxName = wxUser.getNickName();
            //截取名字
            if (wxName == null) {
                wxName = "请设置名字";
            }
            if (wxName.length() > 6) {
                wxName = wxName.substring(0, 6);
            }
            wxName = filterEmoji(wxName);
            userEntity.setName(wxName);
        }
        userDao.update(userEntity);
    }

    /**
     * 去除表情
     *
     * @param source
     * @return
     */
    public String filterEmoji(String source) {
        if (source != null && source.length() > 0) {
            return source.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "*");
        } else {
            return source;
        }
    }


    String getWxId(WxUser wxUser) {
        if (wxUser.getUnionId() == null || wxUser.getUnionId().equals("")) {
            return wxUser.getOpenId();
        } else {
            return wxUser.getUnionId();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity register(String openId, String unionId, String name, String avatar, String phone, String captcha, Long topUserId, String remark) {
/*        if (topUserId == null) {//不存在上家  上家设置为
            topUserId = Const.ADMIN_ID;
        }*/

        if (phone == null || phone.equals("")) {
            throw new RRException("手机号不能为空");
        }

        UserEntity temUser = userDao.findByMobile(phone);
        if (temUser != null) {
            throw new RRException("手机号不能为空!");
        }

        //上级是公司or为null 则不让注册
        if (topUserId == null || topUserId.equals("")) {
            throw new RRException("请扫分享人的二维码进入");
        }
        if (topUserId.equals(Const.ADMIN_ID)) {
            throw new RRException("请扫分享人的二维码进入");
        }
        UserEntity topUser = get(topUserId);
        if (topUser == null) {
            throw new RRException("分享人不存在!");
        }
        if (topUser.getLevelId().equals(LevelEnum.YK.levelId)) {
            throw new RRException(LevelEnum.YK.name + "不能招募");
        }
        if (topUser.getLevelId().equals(LevelEnum.DZ.levelId)) {
            throw new RRException(LevelEnum.DZ.name + "不能招募");
        }
        LevelEntity levelEntity = levelDao.findBase();
        UserEntity userEntity = new UserEntity(phone, openId, unionId, avatar, name, phone, topUser.getTeamCode(), topUser.getId(), null, levelEntity.getId(), new Date(), UserStatusEnum.ACTIVE.getIndex());
        userEntity.setPassword("888888");
        save(userEntity);
        //更新联营等信息
//        changeRidFidByPid(userEntity.getId(), userEntity.getPid());
//        updateTeam(userEntity, topUser);
        //通知
        noticeService.sendUserIn(topUser.getOpenId(), userEntity.getName(), "");
        return userEntity;
    }



    @Override
    public UserEntity register(String openId, Long topUserId) {
        WxUser wxUser = wxWebService.getWxUserBySdk(openId);
        //判断用户是否存在
        String wxId = wxUser.getOpenId();
        UserEntity userEntity = userDao.findByWxId(wxId);
        //更新unionId
        if (wxUser.getUnionId() != null && !wxUser.getUnionId().equals("")) {
            UserEntity tem = userDao.findByWxId(wxUser.getUnionId());
            if (userEntity != null && tem == null) { //unionid后面录入
                userEntity.setUnionId(wxUser.getUnionId());
            } else {
                userEntity = tem;
            }
        }
        if (userEntity != null) {
            userEntity.setOpenId(wxUser.getOpenId());
            userEntity.setUnionId(wxUser.getUnionId());
            update(userEntity);
            return userEntity;
        }
        //如果不存在则注册
        userEntity = register(openId, wxUser.getUnionId(), wxUser.getNickName(), wxUser.getHeadImgUrl(), null, null, topUserId, "关注公众号注册");
        return userEntity;
    }

    @Override
    public UserEntity registerBySend(String phone, Long pid) {
        return register(null, null, null, null, phone, null, pid, "赠送名额注册");
    }

    @Autowired
    private NoticeService noticeService;

    public static void main(String[] args) {
//        System.out.println((int) Math.ceil(111111 + Math.random() * 888888));
//        System.out.println(System.currentTimeMillis());
        System.out.printf(getCodeNumber("ZMZ1234"));
    }

    @Autowired
    private LevelDao levelDao;

    private String createCode(String tCode) {
        String code = tCode + (int) Math.ceil(111111 + Math.random() * 888888);
        int count = 0;
        while (findByCode(code) != null) {
            count++;
            code = tCode + (int) Math.ceil(111111 + Math.random() * 888888);
            if (count > 5) {
                throw new RRException("生成代理失败");
            }
        }
        return code;
    }


    //团队
    private void createTeam(UserEntity userEntity, UserEntity topUser) {
        String team = userEntity.getTeam() + topUser.getId() + "/";
        userEntity.setTeam(team);
        update(userEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity update(Long userId, String phone, String password, String name, Boolean async, String topPhone) {
        UserEntity userEntity = userDao.get(userId);
//        Boolean canReward = false;
//        //首次完善信息才送
//        if (userEntity.getMobile() == null || "".equals(userEntity.getMobile()) || userEntity.getMobile().equals("null")) {
//            canReward = true;
//        }
        if (async == null || !async) {
            if (password != null && !password.equals("")) {
                userEntity.setPassword(password);
            } else {
                userEntity.setPassword("888888");
            }

            userEntity.setName(name);
            validatePhone(phone, userEntity);
            userEntity.setMobile(phone);
            //修改上级
            if (topPhone != null && !"".equals(topPhone)) {
                UserEntity topUser = userDao.findByMobile(topPhone);
                if (topUser == null) {
                    throw new RRException("系统不存在该手机号");
                }
                userEntity.setPid(topUser.getId());
                userEntity.setRid(topUser.getId());
            }
            userDao.update(userEntity);
//            if (canReward) {
//                accountService.rewardRegister(userId);
//            }
            return userEntity;
        } else {//同步账号  后期去掉 TODO 就是切换账号
            if (userEntity.getMobile() != null && !userEntity.getMobile().equals("")) {
//                throw new RRException("请勿重复同步!");
                return userEntity;
            }

            UserEntity tem = userDao.findByMobile(phone);
            if (tem == null) {
                throw new RRException("手机号码不存在!");
            }

            if (tem.getOpenId() != null && !tem.getOpenId().equals("")) {
                throw new RRException("账号已被同步!");
            }

            tem.setAvatar(userEntity.getAvatar());
            tem.setName(userEntity.getName());
            tem.setUnionId(userEntity.getUnionId());
            tem.setOpenId(userEntity.getOpenId());
            userDao.update(tem);
            userEntity.setOpenId("");
            userEntity.setUnionId("");
            userDao.update(userEntity);//直接删除
            return tem;
        }


    }

    @Override
    public void validatePhone(String phone, UserEntity userEntity) {
        if (phone == null || phone.equals("")) {
            throw new RRException("请填写手机号");
        }
        if (phone.length() != 11) {
            throw new RRException("手机号有误");
        }
        try {
            UserEntity tem = userDao.findByMobile(phone);
            if (tem != null && userEntity != null && !tem.getId().equals(userEntity.getId())) {
                throw new RRException("手机号码已经被占用!");
            }
            if (tem != null && userEntity == null) {
                throw new RRException("手机号码已经被占用");
            }
        } catch (Exception e) {
            throw new RRException("手机号码已经被占用!");
        }
    }

    public void validateCode(String code, UserEntity user) {
        if (code == null || code.equals("")) {
            throw new RRException("编号不存在!");
        }
        if (CodeUtil.getTeam(code) == null) {
            throw new RRException("团队编码不存在!");
        }
        if (CodeUtil.getCodeNumber(code).length() != 6) {
            throw new RRException("");
        }
        UserEntity tem = userDao.findByCode(code);
        if (tem != null && !tem.getId().equals(user.getId())) {
            throw new RRException("编号已存在!");
        }
    }

    @Override
    public void validateUser(Long userId) {
        UserEntity userEntity = userDao.get(userId);
        if (userEntity.getStatus() != null && userEntity.getStatus().equals(UserStatusEnum.BAN.getIndex())) {
            throw new RRException("已禁止操作");
        }
    }

    @Override
    public UserEntity getLvTopUser(Long userId) {
        UserEntity userEntity = get(userId);
        if (userEntity == null) {
            throw new RRException("用户:" + userId + "不存在");
        }
        LevelEntity userLv = levelDao.findByUserId(userId);
        UserEntity topUser = get(userEntity.getPid());
        int num = 0;
        while (topUser != null) {
            num++;
            if (num > 100) {
                throw new RRException("层级关系错误,请联系管理员");
            }
            LevelEntity topLv = levelDao.findByUserId(topUser.getId());
            //上级是公司或者高级别用户
            if (topUser.getId().equals(Const.ADMIN_ID) || topLv.getLv() < userLv.getLv()) {
                break;
            }
            topUser = get(topUser.getPid());
        }
        return topUser;
    }

    @Override
    public UserEntity findByWxId(String wxId) {
        return userDao.findByWxId(wxId);
    }

    @Override
    public UserEntity findByAny(String info) {
        return userDao.findByAny(info);
    }

    @Autowired
    private AccountRecordDao accountRecordDao;

    /**
     * 查询当前用户信息并查询当前用户的总粉丝数，总代理数，总佣金
     *
     * @param userId
     * @return
     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public UserEntityVo findNowUserInfo(Long userId) {
//        UserEntityVo userEntityVo = new UserEntityVo();
//        UserEntity userEntity = this.userDao.get(userId);
//        userEntityVo.setUserEntity(userEntity);
//        Long lv = this.levelDao.findBase().getId();
////      获取粉丝数
//        // 获取总粉丝数
//        List<UserEntity> userEntities = this.userDao.findByTop(userId);
//        List<UserEntity> results = new ArrayList<>();
//        List<UserEntity> userEntityList = new ArrayList<>();
//
//
//        results.addAll(userEntities);
//        results = findByLists(results, userEntities);
//
//        for (UserEntity result : results) {
//            if (result.getLevelId() == lv) {
////                System.out.println(result.getName()+result.getLevelId());
//                continue;
//            }
//            userEntityList.add(result);
//        }
//        userEntityVo.setAgentNum(userEntityList.size());
//        userEntityVo.setFansNum(results.size() - userEntityList.size());
//
//        //TODO
//        BigDecimal totalShareDone = this.accountRecordDao.total(Const.ADMIN_ID, userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(), null, AccountRecordBusEnum.SHARE_REWARD.getIndex());
//        BigDecimal totalAreaDone = this.accountRecordDao.total(Const.ADMIN_ID, userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(), null, AccountRecordBusEnum.AREA_REWARD.getIndex());
//        BigDecimal totalShareWait = this.accountRecordDao.total(Const.ADMIN_ID, userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(), null, AccountRecordBusEnum.SHARE_REWARD.getIndex());
//        BigDecimal totalAreaWait = this.accountRecordDao.total(Const.ADMIN_ID, userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(), null, AccountRecordBusEnum.AREA_REWARD.getIndex());
//        BigDecimal bigDecimal = this.accountRecordDao.totalByInfo(Const.ADMIN_ID, userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(), AccountRecordBusEnum.TRANSFER.getIndex(), "%" + Const.REWARD_TRANSFER + "%");
//        BigDecimal decimal = this.accountRecordDao.totalByInfo(Const.ADMIN_ID, userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(), AccountRecordBusEnum.TRANSFER.getIndex(), "%" + Const.REWARD_TRANSFER + "%");
//        if (bigDecimal == null) {
//            bigDecimal = BigDecimal.ZERO;
//        }
//        if (decimal == null) {
//            decimal = BigDecimal.ZERO;
//        }
//        if (totalShareDone == null) {
//            totalShareDone = BigDecimal.ZERO;
//        }
//
//        if (totalShareWait == null) {
//            totalShareWait = BigDecimal.ZERO;
//        }
//
//        if (totalAreaDone == null) {
//            totalAreaDone = BigDecimal.ZERO;
//        }
//        if (totalAreaWait == null) {
//            totalAreaWait = BigDecimal.ZERO;
//        }
//        totalShareDone = totalShareDone.add(bigDecimal);
//        totalShareDone = totalShareDone.add(totalAreaDone);
//        totalShareWait = totalShareWait.add(decimal);
//        totalShareWait = totalShareWait.add(totalAreaWait);
//        BigDecimal backDone = this.accountRecordDao.total(userId, Const.ADMIN_ID, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(), Const.REWARD_TRANSFER, AccountRecordBusEnum.BACK.getIndex());
//        if (backDone != null) {
//            totalShareDone = totalShareWait.subtract(backDone);
//        }
//
//
//        userEntityVo.setTotalDone(totalShareDone);
//        userEntityVo.setTotalWait(totalShareWait);
//        return userEntityVo;
//    }

    @Override
    public UserEntity findLeader(Long userId) {
        UserEntity user = get(userId);
        UserEntity parent = null;
        int index = 0;
        while (!user.getId().equals(Const.ADMIN_ID)) {
            LevelEntity levelEntity = levelDao.get(user.getLevelId());
            //找到领导人 包括自己
            if (levelEntity.getName().equals("联盟单位.")) {
                parent = user;
                break;
            }
            user = userDao.get(user.getPid());
            index++;
            if (index > 50) {
                throw new RRException("上下级关系有误");
            }
        }
        return parent;
    }

    private List<UserEntity> findByLists(List<UserEntity> results, List<UserEntity> userEntities) {
        if (userEntities.size() > 0) {
            List<UserEntity> tems = userDao.findByList(userEntities);
            results.addAll(tems);
            findByLists(results, tems);
        }
        return results;
    }

    @Autowired
    private AreaDao areaDao;

    @Value("${AUTH-IMG}")
    private String authImg;

    @Override
    public void createAuthImg(Long userId, HttpServletResponse response) {
        UserEntity userEntity = get(userId);
        try {
            URL url = new URL(authImg);
            BufferedInputStream inputStream = new BufferedInputStream(url.openStream());
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            Graphics g = bufferedImage.getGraphics();
            g.setColor(Color.BLACK);
            g.setFont(new Font("宋体", Font.BOLD, 30));
            //名字
            g.drawString(userEntity.getName(), 420, 625);
            //手机号
            g.drawString(userEntity.getMobile(), 420, 700);
            //区域代理 TODO 搜索区域代理
            List<AreaEntity> areaEntityList = this.areaDao.findByUserId(userEntity.getId());
            if (!areaEntityList.isEmpty()) {

                g.drawString(areaEntityList.get(0).getName() + "区域代理", 420, 866);

            }//编号
            g.drawString(userEntity.getCode(), 420, 950);
            //级别
            LevelEntity levelEntity = levelDao.findByUserId(userId);
            g.drawString(levelEntity.getName(), 420, 1026);
            //时间
            g.drawString(DateUtil.dateFormat("yyyy-MM-dd", userEntity.getTime()), 290, 1135);
            g.dispose();
            ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
            IOUtils.closeQuietly(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public List<UserEntity> findAllTop(Long userId) {
        UserEntity user = userDao.get(userId);
        List<UserEntity> tops = new ArrayList<>();
        int i = 0;
        while (user != null && !user.getPid().equals(Const.ADMIN_ID)) {
            if (i > 50) {
                throw new RRException("层级错误循环");
            }
            UserEntity top = userDao.get(user.getPid());
            if (top != null) {
                tops.add(top);
                user = top;
            } else {
                break;
            }
        }
        return tops;
    }

    @Override
    public void eachTop(Long userId, Predicate<UserEntity> consumer) {
        UserEntity user = userDao.get(userId);
        Integer count = 0;
        while (user.getPid() != null && !user.getPid().equals(Const.ADMIN_ID)) {
            count++;
            if (count > 50) {
                throw new RRException("遍历上级循环!");
            }
            user = userDao.get(user.getPid());
            //上级不存在也跳出
            if (user == null || consumer.test(user)) {
                break;
            }
        }
    }


    @Override
    public void eachChild(List<Long> topIds, Predicate<List<UserEntity>> consumer, Integer count) {
        count++;
        if (count > 50) {
            throw new RRException("层级错误");
        }
        List<UserEntity> users = userDao.findByTops(topIds);
        if (consumer.test(users)) {
            return;
        }
        if (!users.isEmpty()) {
            eachChild(users.stream().map(UserEntity::getId).collect(Collectors.toList()), consumer, count);
        }
    }

    //找到下面所有人 出现级别大约等于的 就不找了
    public void eachChild(List<Long> topIds, Long levelId, Predicate<List<UserEntity>> consumer, Integer count) {
        count++;
        List<UserEntity> users = userDao.findByTops(topIds);
        if (consumer.test(users)) { //传递出去的
            return;
        }
        //只需要比这个levelId级别小的
        users = users.stream().filter(user -> LevelEnum.getLv(user.getLevelId()) > LevelEnum.getLv(levelId)).collect(Collectors.toList());
        //TODO 这里可以改成循环 不用递归 参考eachTop
        if (!users.isEmpty()) {
            eachChild(users.stream().map(UserEntity::getId).collect(Collectors.toList()), levelId, consumer, count);
        }
        if (count > 50) {
            throw new RRException("层级循环了!");
        }
    }


    @Override
    public void eachChildByMap(List<Long> topIds, Map<Long, List<UserEntity>> source, Predicate<List<UserEntity>> consumer) {
        List<UserEntity> users = new ArrayList<>();
        if (source != null) { //有就从缓存中取
            for (Long id :
                    topIds) {
                if (source.get(id) != null) {
                    users.addAll(source.get(id));
                }
            }
        } else { //没有就从数据库取
            users = userDao.findByTops(topIds);
        }
        if (consumer.test(users)) {
            return;
        }
        if (!users.isEmpty()) {
            eachChildByMap(users.stream().map(UserEntity::getId).collect(Collectors.toList()), source, consumer);
        }
    }

    @Override
    public void eachChildByMap(UserEntity topUser, Map source, Predicate<UserEntity> consumer) {
        List<UserEntity> users = (List<UserEntity>) source.get(topUser.getId());
        if (users == null) return;
        users.forEach(user -> {
            if (consumer.test(user)) {
                return;
            }
            eachChildByMap(user, source, consumer);
        });
    }

    @Override
    public void eachVOChild(List<Long> topIds, Predicate<List<UserVO>> consumer) {
        List<UserVO> users = userDao.findVOByTops(topIds);
        if (consumer.test(users)) {
            return;
        }
        if (!users.isEmpty()) {
            eachVOChild(users.stream().map(UserVO::getId).collect(Collectors.toList()), consumer);
        }
    }

    @Override
    public void initUserRidFid(UserEntity user) {
        //重置 实时更新
        user.setFid(null);
        user.setRid(null);
        eachTop(user.getId(), top -> {

            //上级信息
            if (user.getPInfo() == null) {
                user.setPInfo(top.getMobile() + "-" + top.getName());
            }

            if (top.getLevelId() != null) {
                //如果是联营
                if (top.getLevelId().equals(LevelEnum.LY.levelId)) {
                    if (user.getRid() == null) {
                        user.setRid(top.getId());
                        user.setRInfo(top.getMobile() + "-" + top.getName());
                    }
                }
                //如果是服务商
                if (top.getLevelId().equals(LevelEnum.FW.levelId)) {
                    // 联营会截断服务商
                    if (user.getRid() == null && user.getFid() == null) {
                        user.setFid(top.getId());
                        user.setFInfo(top.getMobile() + "-" + top.getName());
                    }
                }
            }
            //都有了
            if (user.getRid() != null && user.getFid() != null) {
                return true;
            }
            return false;
        });
    }

    @Override
    public void initUserTeamCount(UserEntity user) {
        List<UserEntity> childList = new ArrayList<>();
        List<UserEntity> teamList = new ArrayList<>();
        Integer count = 0;
        eachChild(Arrays.asList(user.getId()), users -> {
            if (childList.isEmpty()) {
                childList.addAll(users);
            }
            teamList.addAll(users);
            return false;
        }, count);
        user.setTeamCount(teamList.size());
        user.setChildCount(childList.size());
    }

    //先循环第一层直接的判断 然后排除符合的 循环第一层 每一层判断
    private List<UserEntity> validateVip(MultiValuedMap source, Long userId, Integer totalCount, Predicate<UserEntity> predicate) {
        List<UserEntity> res = new ArrayList<>();
        List<UserEntity> childList = (List<UserEntity>) source.get(userId);
        //直接下级有三个满足的
//        AtomicReference<Integer> count = new AtomicReference<>(0);
        List<UserEntity> newChildList = new ArrayList<>();
        for (UserEntity temUser : childList) {
            if (predicate.test(temUser)) {//是真实的
                res.add(temUser);
                if (res.size() >= totalCount) { //满足条件直接返回
                    return res;
                }
            } else { //不满足条件 收集 判断下线
                newChildList.add(temUser);
            }
        }
//        childList = childList.stream().filter(child -> {
//            if (predicate.test(child)) {//是真实的
//                res.add(child);
//                return false;
//            }
//            return true;
//        }).collect(Collectors.toList());
        //层级下面有的 每层下面只能累计一个
//        for (UserEntity temUser : newChildList
//        ) {
//            eachChildByMap(Arrays.asList(temUser.getId()), source, users -> {
//                for (UserEntity child : users) {
//                    if (predicate.test(child)) {
//                        res.add(child);
//                        return true;
//                    }
//                }
//                return false;
//            });
//        }
        return res;
    }


    @Override
    public List<UserEntity> isHVip(Long userId, MultiValuedMap source) {
        return validateVip(source, userId, 3, child -> canUpHVip(child, source));
    }


    @Override
    public List<UserEntity> isLVip(Long userId, MultiValuedMap source) {
        return validateVip(source, userId, 3, child -> canUpLVip(child, source));
    }


    /**
     * 直推三个白钻及以上
     * 这种情况一般不会错
     * 所以直接返回粉钻减少计算
     *
     * @param code
     * @return
     */
    @Override
    public Boolean isFVIp(Long userId) {
        UserEntity user = userDao.get(userId);
//        List<UserEntity> userEntities = userDao.findByTop(user.getId());
//        Integer count = 0;
//        for (UserEntity tem:userEntities
//        ) {
//            //白钻或者以上
//            if(LevelEnum.getLv(tem.getLevelId())<=LevelEnum.getLv(LevelEnum.BZ.levelId)){
//                count++;
//            }
//            if(count>=3){
//                break;
//            }
//        }
//        return count>=3;
        return user.getLevelId().equals(50L);
    }

    //是否满足可以升级蓝钻
    private Boolean canUpLVip(UserEntity child, MultiValuedMap source) {
//        //红钻 再判断是否是真实的红钻 红钻都不是不判断了
//        if (child.getLevelId().equals(LevelEnum.HZ.levelId) && isHVip(child.getId(), source).size() >= 3) {
//            return true;
//        }
//        //蓝钻在判断是否真实
//        if (child.getLevelId().equals(LevelEnum.LZ.levelId) && isLVip(child.getId(), source).size() >= 3) {
//            return true;
//        }
//        //粉钻 默认真实
////        if (child.getLevelId().equals(LevelEnum.FZ.levelId) && isFVIp(child.getId())) {
//        if (child.getLevelId().equals(LevelEnum.FZ.levelId)) {
//            return true;
//        }
        return false;
    }

    //是否可以升级红VIP
    private Boolean canUpHVip(UserEntity child, MultiValuedMap source) {
        //红钻
//        if (child.getLevelId().equals(LevelEnum.HZ.levelId) && isHVip(child.getId(), source).size() >= 3) {
//            return true;
//        }
//        //蓝钻
//        if (child.getLevelId().equals(LevelEnum.LZ.levelId) && isLVip(child.getId(), source).size() >= 3) {
//            return true;
//        }
        return false;
    }

    //下面是否有某一角色
    public Boolean childHasLevel(Long userId, List<Long> ids) {
        List<UserEntity> childList = userDao.findByTop(userId);
        return checkChildLevel(childList, ids);
    }

    Boolean checkChildLevel(List<UserEntity> users, List<Long> levelIdList) {
        if (users.isEmpty()) {
            return false;
        }
        List<UserEntity> tems = userDao.findByTops(users.stream().map(UserEntity::getId).collect(Collectors.toList()));
        for (UserEntity tem : tems
        ) {
            if (levelIdList.contains(tem.getLevelId())) {
                return true;
            }
        }
        return checkChildLevel(tems, levelIdList);
    }

    @Override
    public List<UserEntity> findByPid(Long userId) {
        return userDao.findByPid(userId);
    }


    @Resource
    private TokenDao tokenDao;

    @Override
    public UserEntity getLoginUser(String token) {
        TokenEntity tokenEntity = tokenDao.findByToken(token);
        if (tokenEntity == null) {
            return null;
        }
        if (tokenEntity.getExpireTime().before(new Date())) { //已经过期
            return null;
        }
        UserEntity user = userDao.get(tokenEntity.getUserId());
        if (user == null) {
            return null;
        }
        return user;
    }

    @Override
    public UserVO findVO(Long userId) {
        return userDao.findVO(userId);
    }


    @Override
    public List<UserVO> findVOByPid(Long userId, Integer type) {
        if (type == null) {
            type = 0;
        }
        AtomicReference<Integer> count = new AtomicReference<>(0);
        List<UserVO> res = new ArrayList<>();
        Integer finalType = type;
        eachVOChild(Arrays.asList(userId), (users) -> {
            res.addAll(users);
            if (count.get() == finalType) {
                return true;
            }
            count.getAndSet(count.get() + 1);
            return false;
        });
        return res;
    }

    @Override
    public UserVO findVOByAny(String name) {
        return userDao.findVOByAny(name);
    }

    @Override
    public List<UserEntity> findByMonth(Date date) {
        return userDao.findByMonth(date);
    }

    @Override
    public List<UserEntity> finByUserIds(Set<Long> userIds) {
        return userDao.finByUserIds(userIds);
    }

    @Override
    public void down(List<UserVo> userList, HttpServletResponse response) {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=demo.xlsx");
        List<UserDownVO> datas = userList.stream().map(userVo -> {
            String topInfo = "";
            if (userVo.getTopUser() != null) {
                topInfo = userVo.getTopUser().getName() + userVo.getTopUser().getMobile();
            }
            return new UserDownVO(userVo.getUser().getName(), userVo.getUser().getMobile(),
                    topInfo, userVo.getUser().getFInfo(),
                    userVo.getUser().getRInfo(), userVo.getLevel().getName(), userVo.getUser().getTime());
        }).collect(Collectors.toList());
        try {
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
            WriteSheet writeSheet1 = EasyExcel.writerSheet(0, "用户").head(UserDownVO.class).build();
            excelWriter.write(datas, writeSheet1);
            excelWriter.finish();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RRException("导出失败");
        }
    }



    @Value("${Qiniu.img_domain}")
    private String qiniuDomain;

    @Override
    public void update(Long userId, UserUpdateDTO userUpdateDTO) {
        UserEntity user = userDao.get(userId);
        String avatar = userUpdateDTO.getAvatar();
        if(Optional.ofNullable(userUpdateDTO.getNeedDomain()).orElse(false)){
            avatar = qiniuDomain+avatar;
        }
        user.setAvatar(avatar);
        user.setName(userUpdateDTO.getName());
        update(user);
    }

    @Override
    public UserEntity getChatUserInfo(Long userId) {
        UserEntity user = get(userId);
        UserEntity chatUser = new UserEntity();
        chatUser.setId(user.getId());
        chatUser.setLevelId(user.getLevelId());
        chatUser.setUnionId(user.getUnionId());
        chatUser.setAvatar(user.getAvatar());
        chatUser.setName(user.getName());
        chatUser.setDyNumber(user.getDyNumber());
        chatUser.setRemark(user.getRemark());
        chatUser.setMobile(user.getMobile());
        chatUser.setLevelName(LevelEnum.levelOf(user.getLevelId()).name);
        initUserRidFid(chatUser);
        chatUser.setDyNumber(user.getDyNumber());
        chatUser.setRemark(user.getRemark());
        return chatUser;
    }



    @Override
    public Boolean isNewDr(Long levelId, Date date) {
        if(!levelId.equals(LevelEnum.DR.levelId)){ //不是达人
            return  false;
        }
        if(date==null){
            return true;
        }
        // 创建一个表示2023年10月4日的日期对象 1900开始 不是新人才可以分享
        Date targetDate = new Date(123, 9, 4);
        return date.after(targetDate);
    }

    @Override
    public Boolean canShare(Long levelId, Date date) {
        if(LevelEnum.getLv(levelId)>LevelEnum.DR.lv){ //达人级别以下
            return  false;
        }
        //且不是新达人
        return  !isNewDr(levelId,date);
    }

    @Override
    public List<String> findAllOpenId() {
        return userDao.findAllOpenId();
    }
}
